package main

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

func basic() {
	// length.
	str1 := "helloworld!"
	fmt.Println("string is: ", str1)
	fmt.Printf("string length is: %d\n", len(str1))

	// compare.
	str2 := "hi"
	comps := strings.Compare(str1, str2)
	fmt.Printf("Compare result of \"%s\" and \"%s\" is :%d\n", str1, str2, comps)

	// trim.
	str3 := "\t\t123456 \r\n "
	fmt.Printf("str3 is:%s\n", str3)
	fmt.Printf("after trim: %s\n", strings.Trim(str3, " \t\n\r"))

	// find index.
	b := strings.Index(str1, "o")
	e := strings.Index(str1, "!")
	n := strings.Index(str1, "2")
	fmt.Printf("o: %d, !: %d, 2: %d\n", b, e, n)

	// sub-string.
	if b != -1 && e != -1 {
		t := str1[b:e]
		println(t)
	}

	// relect type, kind.
	to := reflect.TypeOf(str1)
	fmt.Println("reflect type of t:", to)
	fmt.Println("reflect type name and type kind:", to.Name(), to.Kind())

	// to lower and upper case.
	str4 := "This is A String With Upper And Lower Case"
	fmt.Println("Orignal string is:", str4)
	fmt.Println("Lower case:", strings.ToLower(str4))
	fmt.Println("Upper case:", strings.ToUpper(str4))

	// replace
	str5 := "Alice go to shop, Alice buy a piece of bread, Alice go home."
	var str6 string = strings.Replace(str5, "Alice", "Bob", -1)
	fmt.Println("Ori-str: ", str5)
	fmt.Println("After replace [repalce count = -1]: ", str6)
	var str7 string = strings.Replace(str5, "Alice", "Candy", 1)
	fmt.Println("After replace [replace count = 1]:", str7)
}

func beginsWith(str1 string, str2 string) bool {
	var lenOfStr2 int = len(str2)
	if len(str1) >= lenOfStr2 {
		if strings.Compare(str1[0:lenOfStr2], str2) == 0 {
			return true
		}
	}
	return false
}

func endsWith(str1, str2 string) bool {
	var lenOfStr2 int = len(str2)
	var lenOfStr1 int = len(str1)
	if lenOfStr1 >= lenOfStr2 {
		if strings.Compare(str1[lenOfStr1-lenOfStr2:], str2) == 0 {
			return true
		}
	}
	return false
}

func contains(str1, str2 string, caseInsensitive bool) bool {
	if caseInsensitive {
		var str3, str4 string
		str3 = strings.ToLower(str1)
		str4 = strings.ToLower(str2)
		return strings.Contains(str3, str4)
	} else {
		return strings.Contains(str1, str2)
	}
}

func remove(str1, str2 string) string {
	ret := str1
	ret = strings.Replace(ret, str2, "", -1)
	return ret
}

func main() {

	basic()

	// begins with
	{
		var str1, str2 string = "a123456", "a1234567"
		if beginsWith(str1, str2) {
			fmt.Printf("[%s] begins with [%s]\n", str1, str2)
		} else {
			fmt.Printf("[%s] does not begins with [%s]\n", str1, str2)
		}

		if beginsWith(str2, str1) {
			fmt.Printf("[%s] begins with [%s]\n", str2, str1)
		} else {
			fmt.Printf("[%s] does not begins with [%s]\n", str2, str1)
		}

		str3 := str1
		if beginsWith(str3, str1) {
			fmt.Printf("[%s] begins with [%s]\n", str3, str1)
		} else {
			fmt.Printf("[%s] does not begins with [%s]\n", str3, str1)
		}
	}

	// ends with
	{
		var str1, str2, str3 string = "A-ends", "ends", "A-ends"
		if endsWith(str1, str2) {
			fmt.Printf("[%s] ends with [%s]\n", str1, str2)
		} else {
			fmt.Printf("[%s] does not ends with [%s]\n", str1, str2)
		}

		if endsWith(str2, str1) {
			fmt.Printf("[%s] ends with [%s]\n", str2, str1)
		} else {
			fmt.Printf("[%s] does not ends with [%s]\n", str2, str1)
		}

		if endsWith(str3, str1) {
			fmt.Printf("[%s] ends with [%s]\n", str3, str1)
		} else {
			fmt.Printf("[%s] does not ends with [%s]\n", str3, str1)
		}
	}

	// Contains with insensitive.
	{
		var str1, str2 string = "ThisIsATestString", "ateststring"
		if contains(str1, str2, true) {
			fmt.Printf("Insensitive: [%s] contains [%s]\n", str1, str2)
		} else {
			fmt.Printf("Insensitive: [%s] not contains [%s]\n", str1, str2)
		}
	}

	{
		var str1, str2 string = "The Object is The last one of The array", "The"
		var str3 = remove(str1, str2)
		fmt.Println("Before remove:", str1)
		fmt.Println("After remove:", str3)
	}

	// String to int
	{
		var str1 string = "1234"
		intVal, err := strconv.Atoi(str1)
		if err == nil {
			fmt.Printf("string to int [%s] => [%d]\n", str1, intVal)
		} else {
			fmt.Printf("Failed to transform string [%s] to int. [%s].", str1, err.Error())
		}

		str1 = "0xa1b2c3d4"
		intVal, err = strconv.Atoi(str1)
		if err == nil {
			fmt.Printf("string to int [%s] => [%d]\n", str1, intVal)
		} else {
			fmt.Printf("Failed to transform string [%s] to int. [%s].\n", str1, err.Error())
		}

		var i64Val uint64
		i64Val, err = strconv.ParseUint(str1, 0, 32)
		if err == nil {
			fmt.Printf("hex string to int [%s] => [%d]\n", str1, i64Val)
		} else {
			fmt.Printf("Failed to transform hex string [%s] to int. [%s].\n", str1, err.Error())
		}
	}

	// is number (dec)
	{
		var str1 string = "123456"
		_, err := strconv.ParseInt(str1, 10, 64)
		if err == nil {
			fmt.Printf("[%s] is a number\n", str1)
		} else {
			fmt.Printf("[%s] is not a number\n", str1)
		}

		str1 = "axbcd1234"
		_, err = strconv.ParseInt(str1, 10, 64)
		if err == nil {
			fmt.Printf("[%s] is a number\n", str1)
		} else {
			fmt.Printf("[%s] is not a number\n", str1)
		}
	}

	// String to int64
	{
		var str1 string = "1234567891234567891"
		var i64Val int64
		i64Val, err := strconv.ParseInt(str1, 10, 64)
		if err == nil {
			fmt.Printf("string to int64 [%s] => [%v]\n", str1, i64Val)
		} else {
			fmt.Printf("Failed to transform string [%s] to int64. [%s].\n", str1, err.Error())
		}
	}

	//String to boolean
	{
		var str1 string = "true"
		bVal, err := strconv.ParseBool(str1)
		if err == nil {
			fmt.Printf("string to boolean [%s] => [%v]\n", str1, bVal)
		} else {
			fmt.Printf("Failed to transform string [%s] to boolean. [%s].\n", str1, err.Error())
		}

		str1 = "false"
		bVal, err = strconv.ParseBool(str1)
		if err == nil {
			fmt.Printf("string to boolean [%s] => [%v]\n", str1, bVal)
		} else {
			fmt.Printf("Failed to transform string [%s] to boolean. [%s].\n", str1, err.Error())
		}

		str1 = "false1"
		bVal, err = strconv.ParseBool(str1)
		if err == nil {
			fmt.Printf("string to boolean [%s] => [%v]\n", str1, bVal)
		} else {
			fmt.Printf("Failed to transform string [%s] to boolean. [%s].\n", str1, err.Error())
		}
	}

	// from boolean
	{
		fmt.Println("convert boolean true to string format:", strconv.FormatBool(true))
		fmt.Println("convert boolean false to string format:", strconv.FormatBool(false))
	}

	// from int
	{
		fmt.Println("int 123456 to string:", strconv.FormatInt(123456, 10))
		fmt.Println("int 0xabcd to hex string: 0x", strconv.FormatInt(0x123456, 16))
	}

	// from Float
	{
		fmt.Println("float 3.1415926 to string (fmt e):", strconv.FormatFloat(3.1415926, 'e', 7, 64))
		fmt.Println("float 3.1415926 to string (fmt f):", strconv.FormatFloat(3.1415926, 'f', 7, 64))
	}

	// split
	{
		str1 := "This-is-a-string-split-by-space."
		t := strings.Split(str1, "-")
		for _, v := range t {
			fmt.Printf("%v\n", v)
		}
	}

	// join
	{
		var strlist = [...]string{"This", "is", "a", "test", "string"}
		str := strings.Join(strlist[:], "-")
		fmt.Println(str)
	}
}
